/*
 * @Author: 0x9DEFA478
 * @Date: 2021-08-21 20:05:18
 * @LastEditTime: 2023-03-19 21:22:28
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "./H_ThreadScheduler_Core.h"
#include "../LL/H_ThreadScheduler_LL.h"




extern H_TS* H_TS_Core;




extern void H_TS_MemoryGetInfo(Hsize* FreeSize,Hsize* AllSize);
extern void H_TS_EnableTickCallback(void (*callback)(void*),void* v);
extern void H_TS_LL_Init(void);




extern void H_TS_TickCallback(void* v);




/**
 * @brief 挂起线程调度 调度器挂起期间 不能使用任何H_TS的方法(防止这些方法恢复了任务调度)
 * @return 无
 */
void H_TS_SchedulerSuspend(){
  oH_TS_SchedulerSuspend();//挂起线程调度
}

/**
 * @brief 恢复任务调度  不能使用任何H_TS的方法(防止这些方法恢复了任务调度)
 * @param IsCallPendSV 0:由调度器决定是否触发PendSV 其他:返回前触发PendSV
 * @return 无
 */
void H_TS_ResumeScheduler(int IsCallPendSV){

  if(IsCallPendSV==0){
    oH_TS_ResumeSchedulerAuto();
  }else{
    oH_TS_ResumeSchedulerFixed();
  }
}

/**
 * @brief 获取CPU使用率
 * @return CPU使用率 单位0.1%
 */
int H_TS_GetCPU_Load(){
  return H_TS_Core->CPU_Load;
}

/**
 * @brief 获取线程的CPU占用率 保证目标线程存在时调用
 * @param Thread 要获取的线程 如果为NULL 代表获取的是调用这个方法的线程
 * @return CPU使用率 单位0.1%
 */
int H_TS_GetThreadCPU_Load(H_TS_Thread* Thread){
  if(Thread==NULL){
    Thread=cH_TS_ThisThread(H_TS_Core);
  }
  return Thread->CPU_Load;
}

/**
 * @brief 设置空闲函数空闲时调用的方法
 * @param IdleProcess 空闲回调
 * @return 无
 */
void H_TS_SetIdleProcess(void (*IdleProcess)(void*)){
  H_TS_Core->IdleProcess=IdleProcess;
}

/**
 * @brief 获取堆栈内存占用
 * @return 堆栈内存占用率 单位0.1%
 */
int H_TS_GetStackUtilization(){
  Hsize FreeSize;
  Hsize AllSize;

  oH_TS_SchedulerSuspend();

  H_TS_MemoryGetInfo(&FreeSize,&AllSize);

  oH_TS_ResumeSchedulerAuto();

  return 1000-1000*FreeSize/AllSize;
}

/**
 * @brief 开始线程调度 使用此方法之前 必须调用H_TS_Init()
 * @return 正常情况 该方法不会返回
 */
void H_TS_StartScheduler(){

  H_TS_LL_Init();
  H_TS_EnableTickCallback(H_TS_TickCallback,NULL);

  oH_TS_CallScheduleISR();//触发调度中断

  for(;;){}
}




//==============================================================================================================================
//
//       锁相关方法
//
//==============================================================================================================================

/**
 * @brief 新建一个锁
 * @return 锁对象 如果为NULL 则失败
 */
H_TS_Lock* new_H_TS_Lock(){
  H_TS_Lock* r;

  oH_TS_SchedulerSuspend();

  r=H_TS_Core->Memory.Malloc(sizeof(H_TS_Lock));
  if(r==NULL){
    oH_TS_ResumeSchedulerAuto();
    return NULL;
  }

  r->Owner=NULL;
  r->ReLockCnt=0;
  r->WaitLockThreads=NULL;

  oH_TS_ResumeSchedulerAuto();

  return r;
}

/**
 * @brief 删除一个锁
 * @param Lock 要删除的锁
 * @return 0:成功 -1:锁正在被其他线程占用
 */
int delete_H_TS_Lock(H_TS_Lock* Lock){

  oH_TS_SchedulerSuspend();

  if(Lock->Owner!=NULL){
    oH_TS_ResumeSchedulerAuto();
    return -1;
  }

  H_TS_Core->Memory.Free(Lock);

  oH_TS_ResumeSchedulerAuto();

  return 0;
}




//==============================================================================================================================
//
//       信号相关方法
//
//==============================================================================================================================

/**
 * @brief 新建一个信号
 * @return 信号对象 如果为NULL 则失败
 */
H_TS_Signal* new_H_TS_Signal(){
  H_TS_Signal* r;

  oH_TS_SchedulerSuspend();

  r=H_TS_Core->Memory.Malloc(sizeof(H_TS_Signal));
  if(r==NULL){
    goto lReturn;
  }

  r->Owner=NULL;
  r->Value=0;

lReturn:
  oH_TS_ResumeSchedulerAuto();
  return r;
}

/**
 * @brief 删除信号
 * @param Signal 要删除的信号
 * @return 0:成功 -1:有线程因此信号阻塞
 */
int delete_H_TS_Signal(H_TS_Signal* Signal){
  int r;

  r=0;

  oH_TS_SchedulerSuspend();

  if(Signal->Owner!=NULL){
    r=-1;
    goto lReturn;
  }

  H_TS_Core->Memory.Free(Signal);

lReturn:
  oH_TS_ResumeSchedulerAuto();
  return r;
}




//==============================================================================================================================
//
//       信号量相关方法
//
//==============================================================================================================================

/**
 * @brief 新建一个信号量
 * @param MaxCount 最大信号量数量
 * @return 信号量对象 如果为NULL 则失败
 */
H_TS_Semaphore* new_H_TS_Semaphore(Hsize MaxCount){
  H_TS_Semaphore* r;

  oH_TS_SchedulerSuspend();

  r=H_TS_Core->Memory.Malloc(sizeof(H_TS_Semaphore));
  if(r==NULL){
    goto lReturn;
  }

  r->Owner=NULL;
  r->AddFlag=0;

  r->Semaphore.I=0;
  r->Semaphore.O=0;
  r->Semaphore.Max=MaxCount;

lReturn:
  oH_TS_ResumeSchedulerAuto();
  return r;
}

/**
 * @brief 删除一个信号量
 * @param Semaphore 要删除的信号量对象
 * @return 0:成功 -1:有线程因此信号量阻塞
 */
int delete_H_TS_Semaphore(H_TS_Semaphore* Semaphore){
  int r;

  r=0;

  oH_TS_SchedulerSuspend();

  if(Semaphore->Owner!=NULL){
    r=-1;
    goto lReturn;
  }

  H_TS_Core->Memory.Free(Semaphore);

lReturn:
  oH_TS_ResumeSchedulerAuto();
  return r;
}




//==============================================================================================================================
//
//       消息队列相关方法
//
//==============================================================================================================================

/**
 * @brief 新建一个消息队列
 * @param NumOfMessages 队列容量大小 队列最大可容纳(NumOfMessage-1)个消息 (全部占用与队列空的偏移指示是一致的,所以队列设计成不能占满)
 * @return 消息队列对象 如果为NULL 则失败
 */
H_TS_MessageQueue* new_H_TS_MessageQueue(Hsize NumOfMessages){
  H_TS_MessageQueue* r;

  oH_TS_SchedulerSuspend();

  r=H_TS_Core->Memory.Malloc(sizeof(H_TS_MessageQueue));
  if(r==NULL){
    goto lReturn;
  }

  r->MessageFIFO.Messages=H_TS_Core->Memory.Malloc(NumOfMessages*2*sizeof(void*));
  if(r->MessageFIFO.Messages==NULL){
    H_TS_Core->Memory.Free(r);
    r=NULL;
    goto lReturn;
  }

  r->Owner=NULL;
  r->AddFlag=0;
  r->MessageFIFO.I=0;
  r->MessageFIFO.O=0;
  r->MessageFIFO.NumOfMessages=NumOfMessages;

lReturn:
  oH_TS_ResumeSchedulerAuto();
  return r;
}

/**
 * @brief 删除一个消息队列
 * @param MessageQueue 要删除的消息队列对象
 * @return 0:成功 -1:有线程因此消息队列阻塞
 */
int delete_H_TS_MessageQueue(H_TS_MessageQueue* MessageQueue){
  int r;

  r=0;

  oH_TS_SchedulerSuspend();

  if(MessageQueue->Owner!=NULL){
    r=-1;
    goto lReturn;
  }

  H_TS_Core->Memory.Free((void*)MessageQueue->MessageFIFO.Messages);
  H_TS_Core->Memory.Free(MessageQueue);

lReturn:
  oH_TS_ResumeSchedulerAuto();
  return r;
}



//==============================================================================================================================
//
//       复合队列相关方法
//
//==============================================================================================================================




/**
 * @brief 新建一个复合队列
 * @param NumOfMessages 每一个队列的最大容纳个数+1 (最大容纳数=NumOfMessages-1)
 * @param MessageSize 每个信息大小 单位:字节
 * @param NumOfQueues 队列个数
 * @return 复合队列对象 如果为NULL 则失败
 */
H_TS_MultipleQueue* new_H_TS_MultipleQueue(Hsize NumOfMessages,Hsize MessageSize,Hsize NumOfQueues){
  H_TS_MultipleQueue* r;

  oH_TS_SchedulerSuspend();

  r=H_TS_Core->Memory.Malloc(sizeof(H_TS_MultipleQueue));
  if(r==NULL){
    goto lResult;
  }

  r->Queues=H_TS_Core->Memory.Malloc(NumOfQueues*sizeof(struct _H_TS_MultipleQueue_SubQueue));
  if(r->Queues==NULL){
    H_TS_Core->Memory.Free(r);
    r=NULL;
    goto lResult;
  }

  for(Hsize i=0;i<NumOfQueues;i++){
    struct _H_TS_MultipleQueue_SubQueue* subQueue;

    subQueue=&((struct _H_TS_MultipleQueue_SubQueue*)r->Queues)[i];

    subQueue->Messages=H_TS_Core->Memory.Malloc(NumOfMessages*MessageSize);
    if(subQueue->Messages==NULL){
      while(i>0){
        i--;
        subQueue=&((struct _H_TS_MultipleQueue_SubQueue*)r->Queues)[i];
        H_TS_Core->Memory.Free((void*)subQueue->Messages);
      }
      H_TS_Core->Memory.Free(r->Queues);
      H_TS_Core->Memory.Free(r);
      r=NULL;
      goto lResult;
    }

    subQueue->I=0;
    subQueue->O=0;
  }
  
  r->Owner=NULL;
  r->AddFlag=0;
  r->ReEnter=0;
  r->NumOfQueues=NumOfQueues;
  r->NumOfMessages=NumOfMessages;
  r->MessageSize=MessageSize;

lResult:
  oH_TS_ResumeSchedulerAuto();
  return r;
}

/**
 * @brief 删除一个复合队列
 * @param MultipleQueue 要删除的复合队列
 * @return 0:成功 -1:有线程因此复合队列阻塞
 */
int delete_H_TS_MultipleQueue(H_TS_MultipleQueue* MultipleQueue){
  Hsize NumOfQueues;
  int r;

  r=0;

  oH_TS_SchedulerSuspend();

  if(MultipleQueue->Owner!=NULL){
    goto lReturn;
  }

  NumOfQueues=MultipleQueue->NumOfQueues;
  for(Hsize i=0;i<NumOfQueues;i++){
    struct _H_TS_MultipleQueue_SubQueue* subQueue;

    subQueue=&((struct _H_TS_MultipleQueue_SubQueue*)MultipleQueue->Queues)[i];

    H_TS_Core->Memory.Free((void*)subQueue->Messages);
  }
  H_TS_Core->Memory.Free(MultipleQueue->Queues);
  H_TS_Core->Memory.Free(MultipleQueue);

lReturn:
  oH_TS_ResumeSchedulerAuto();
  return r;
}



